﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Net;
using System.Reflection.Metadata;
using System.Runtime.ConstrainedExecution;
using System.Text.Json;
using LightCAD.MathLib;

namespace LightCAD.Core.Elements
{
    public class LcArc : LcCurve2d
    {
        public Vector2 Center { get => this.Arc.Center; set => this.Arc.Center = value; }
        public double Radius { get => this.Arc.Radius; set => this.Arc.Radius = value; }
        public double StartAngle { get => this.Arc.StartAngle; set => this.Arc.StartAngle = value; }
        public double EndAngle { get => this.Arc.EndAngle; set => this.Arc.EndAngle = value; }
        public double MoveAngle;
        public Vector2 Startp { get => this.Arc.Startp; set => this.Arc.Startp = value; }
        public Vector2 Endp { get => this.Arc.Endp; set => this.Arc.Endp = value; }
        public Vector2 Midp { get => this.Arc.Midp; set => this.Arc.Midp = value; }
        public double ArcLength;

        public Arc2d Arc => this.Curve as Arc2d;
        public LcArc()
        {
            this.Type = BuiltinElementType.Arc;
            this.Curve = new Arc2d();
        }
        public LcArc(Vector2 center, double radius, double startAngle, double endAngle) : this()
        {
            this.Center = center;
            Radius = radius;
            this.StartAngle = startAngle;
            this.EndAngle = endAngle;
        }
        public LcArc(double centerX, double centerY, double radius, double startAngle, double endAngle)
        {
            this.Center.X = centerX;
            this.Center.Y = centerY;
            Radius = radius;
            this.StartAngle = startAngle;
            this.EndAngle = endAngle;
        }

        public void LoadArcStatsProperty()
        {
            //判断是圆心画弧还是三点画弧
            if(this.Center == null)   //如果圆心等于空  就代表不用圆心画弧
            {
                this.Center =GeoUtils.GetCenter(Startp, Midp, Endp);
            }
            else
            {
                this.Center = this.Center;
            }

                this.Radius = Math.Sqrt(Math.Pow(Center.X - Endp.X, 2) + Math.Pow(Center.Y - Endp.Y, 2)); //计算半径

                this.StartAngle = ThreePointGetAngle(new Vector2(Center.X + 100, Center.Y), Center, this.Startp, true);
                this.EndAngle = ThreePointGetAngle(new Vector2(Center.X + 100, Center.Y), Center, this.Endp, true);
                this.MoveAngle = 0;
                var pdangle = ThreePointGetAngle(this.Startp, this.Midp, this.Endp);
                if (pdangle > 180 || (pdangle < 0 && pdangle > -180))
                {
                    if (this.StartAngle > 0)
                    {
                        this.MoveAngle = 360 - this.StartAngle + this.EndAngle;
                    }
                    else
                    {
                        this.MoveAngle = 360 + this.EndAngle - this.StartAngle;
                    }
                }

                  else
                {
                    if (this.StartAngle > 0)
                    {
                        this.MoveAngle = -this.StartAngle + this.EndAngle - 360;
                    }
                    else
                    {
                        this.MoveAngle = -(360 + this.StartAngle) + this.EndAngle;
                    }
                }

                if (this.MoveAngle < -360)
                {
                    this.MoveAngle = this.MoveAngle + 360;
                }
                if (this.MoveAngle > 360)
                {
                    this.MoveAngle = this.MoveAngle - 360;
                }

                var a = Startp - Center;
                var b = Endp - Center;
                var m = a + b;
                m.Normalize();
                m = m * Radius;
                this.Midp = Center + m;
                if (Math.Abs(this.MoveAngle) > 180)
                {
                    this.Midp = Vector2.Rotate(this.Midp, this.Center, 180);
                }
                ArcLength = MoveAngle * 2 * Math.PI * Radius / 360;
            
        }


        //public static Vector2 GetCenter(Vector2 startp, Vector2 midp, Vector2 endp)
        //{
        //    Vector2 Center = new Vector2();
        //    double a = startp.X - midp.X;
        //    double b = startp.Y - midp.Y;
        //    double c = startp.X - endp.X;
        //    double d = startp.Y - endp.Y;
        //    double e = ((startp.X * startp.X - midp.X * midp.X) - (midp.Y * midp.Y - startp.Y * startp.Y)) / 2;
        //    double f = ((startp.X * startp.X - endp.X * endp.X) - (endp.Y * endp.Y - startp.Y * startp.Y)) / 2;

        //    // 圆心位置 
        //    var x = (e * d - b * f) / (a * d - b * c);
        //    var y = (a * f - e * c) / (a * d - b * c);
        //    Center.X = x;
        //    Center.Y = y;
        //    return Center;
        //}

        /// <summary>
        /// 三点确定角度
        /// </summary>
        /// <param name="startpoint"></param>
        /// <param name="centerpoint"></param>
        /// <param name="endpoint"></param>
        /// <param name="reversal">是否开启顺时针180为正，逆时针180为负,默认为逆时针负角度</param>
        /// <returns></returns>
        public double ThreePointGetAngle(Vector2 startpoint, Vector2 centerpoint, Vector2 endpoint, bool reversal = false)
        {
            double angle = 0;
            var so = new Vector2(startpoint.X - centerpoint.X, startpoint.Y - centerpoint.Y);
            var eo = new Vector2(endpoint.X - centerpoint.X, endpoint.Y - centerpoint.Y);
            var pddir = (so.X * eo.Y) - (so.Y * eo.X);
            angle = (so.Angle() - eo.Angle()) / Math.PI * 180;
            if (reversal)
            {
                angle = (so.Angle() + (pddir < 0 ? (2 * Math.PI - eo.Angle()) : -eo.Angle())) / Math.PI * 180;
            }

            return angle;
        }
        /// <summary>
        /// 圆弧的盒子算法
        /// </summary>
        /// <returns></returns>
        public override Box2 GetBoundingBox()
        {
            double cMaxX = 0;
            double cMaxY = 0;
            double cMinX = 0;
            double cMinY = 0;
            double start = this.StartAngle * 180 / Math.PI;
            double end = this.EndAngle * 180 / Math.PI;
            if (start < 0)
            {
                start += 360;
            }
            if (end < 0)
            {
                end += 360;
            }
            if ((start <= 90 && start >= 0 && end <= 90 && end > 0) || (start > 90 && start <= 180 && end > 90 && end <= 180)
                || (start > 180 && start <= 270 && end > 180 && end <= 270) || (start > 270 && start <= 360 && end > 270 && end <= 360)) //起点端点都在    
            {
                if (start < end)
                {
                    cMaxX = this.Startp.X;
                    cMinX = this.Endp.X;
                    cMaxY = this.Endp.Y;
                    cMinY = this.Startp.Y;
                }
                if (end < start)
                {
                    cMaxY = this.Center.Y + Radius;
                    cMinY = this.Center.Y - Radius;
                    cMaxX = this.Center.X + Radius;
                    cMinX = this.Center.X - Radius;
                }
            }
            if (start <= 90 && start >= 0 && end > 90 && end <= 180) //端点在第二象限
            {
                cMaxX = this.Startp.X;
                cMaxY = this.Center.Y + Radius;
                cMinX = this.Endp.X;
                if (this.Startp.Y <= this.Endp.Y)
                {
                    cMinY = this.Startp.Y;
                }
                if(this.Startp.Y > this.Endp.Y)
                {
                    cMinY = this.Endp.Y;
                }
            }
            if(start <= 90 && start >= 0 && end > 180 && end <= 270) //端点在第三象限
            {
                cMaxX = this.Startp.X;
                cMaxY = this.Center.Y + Radius;
                cMinX = this.Center.X - Radius;
                cMinY = this.Endp.Y;
            }
            if (start <= 90 && start >= 0 && end > 270 && end <= 360)//端点在第四象限
            {
                if(this.Startp.X>= this.Endp.X)
                {
                    cMaxX = this.Startp.X;
                }
                else
                {
                    cMaxX = this.Endp.X;
                }
                cMaxY=this.Center.Y + Radius;
                cMinX=this.Center.X - Radius;
                cMinY=this.Center.Y - Radius;
            }

            if(start >90 && start<=180 && end <= 90 && end > 0) //起点在第二象限，端点在第一象限
            {
                cMaxX= this.Center.X + Radius;
                cMinX = this.Center.X - Radius;
                cMinY = this.Center.Y - Radius;
                if(this.Startp.Y >= this.Endp.Y)
                {
                    cMaxY = this.Startp.Y;
                }
                else
                {
                    cMaxY = this.Endp.Y;
                }
            }
            if(start > 90 && start <= 180 && end > 180 && end <= 270) //端点在第三象限
            {
                if (this.Startp.X >= this.Endp.X)
                {
                    cMaxX=this.Startp.X;
                }
                else
                {
                    cMaxX = this.Endp.X;
                }
                cMinX = this.Center.X - Radius;
                cMinY = this.Endp.Y;
                cMaxY = this.Startp.Y;
            }
            if(start > 90 && start <= 180 && end > 270 && end <= 360) //端点在第四象限
            {
                cMaxX = this.Endp.X;
                cMinX = this.Center.X - Radius;
                cMaxY = this.Startp.Y;
                cMinY = this.Center.Y - Radius;
            }

            if (start > 180 && start <= 270 && end > 0 && end <= 90) //起点在第三象限 端点在第一象限
            {
                cMaxX = this.Center.X + Radius;
                cMinX = this.Startp.X;
                cMaxY = this.Endp.Y;
                cMinY = this.Center.Y - Radius;
            }
            if (start > 180 && start <= 270 && end > 90 && end <= 180) //端点在第二象限
            {
                cMaxX = this.Center.X + Radius;
                cMaxY = this.Center.Y + Radius;
                if (this.Startp.X <= this.Endp.X)
                {
                    cMinX = this.Startp.X;
                }
                else
                {
                    cMinX = this.Endp.X;
                }
                cMinY = this.Center.Y - Radius;
            }
            if (start > 180 && start <= 270 && end > 270 && end <= 360) //端点在第四象限
            {
                cMaxX = this.Endp.X;
                cMinX = this.Startp.X;
                if (this.Startp.Y >= this.Endp.Y)
                {
                    cMaxY = this.Startp.Y;
                }
                else
                {
                    cMaxY = this.Endp.Y;
                }
                cMinY = this.Center.Y - Radius;
            }

            if (start > 270 && start <= 360 && end > 0 && end <= 90) //起点在第四象限，端点在第一象限
            {
                cMaxX = this.Center.X+Radius;
                if (this.Startp.X <= this.Endp.X)
                {
                    cMinX = this.Startp.X;
                }
                else
                {
                    cMinX = this.Endp.X;
                }
                cMaxY = this.Endp.Y;
                cMinY = this.Startp.Y;
            }
            if (start > 270 && start <= 360 && end > 90 && end <= 180) //起点在第四象限，端点在第二象限
            {
                cMaxX = this.Center.X + Radius;
                cMinX = this.Endp.X;
                cMaxY = this.Center.Y + Radius;
                cMinY = this.Startp.Y;
            }
            if (start > 270 && start <= 360 && end > 180 && end <= 270) //起点在第四象限，端点在第三象限
            {
                cMaxX = this.Center.X + Radius;
                cMinX = this.Center.X - Radius;
                cMaxY = this.Center.Y + Radius;
                if(this.Startp.Y >= this.Endp.Y)
                {
                    cMinY = this.Endp.Y;
                }
                else
                {
                    cMinY = this.Startp.Y;
                }
            }

            return new Box2().SetFromPoints(new Vector2(cMinX, cMinY), new Vector2(cMaxX, cMaxY));
        }
        public override Box2 GetBoundingBox(Matrix3 matrix)
        {

            return new Box2().SetFromPoints(matrix.MultiplyPoint(this.Startp), matrix.MultiplyPoint(this.Endp));
        }

     
        public override bool IntersectWithBox(Polygon2d testPoly, List<RefChildElement> intersectChildren = null)
        {
            var thisBox = this.BoundingBox;
            if (!thisBox.IntersectsBox(testPoly.BoundingBox))
            {
                //如果元素盒子，与多边形盒子不相交，那就可能不相交
                return false;
            }
            else
                return true;
            //Arc2d arc2D = new Arc2d();
            //arc2D.IsClockwise = false;
            //arc2D.StartAngle = this.StartAngle;
            //arc2D.EndAngle = this.EndAngle;
            //arc2D.Center = this.Center;
            //arc2D.Radius = this.Radius;
            //return GeoUtils.IsPolygonIntersectArc(testPoly.Points, arc2D);
        }
      
        public override bool IncludedByBox(Polygon2d testPoly, List<RefChildElement> includedChildren = null)
        {
            var thisBox = this.BoundingBox;
            if (!thisBox.IntersectsBox(testPoly.BoundingBox))
            {
                return false;
            }
            else
                return true;
            return GeoUtils.IsPolygonContainsLine(testPoly.Points, this.Startp, this.Endp);
        }

        public override LcElement Clone()
        {
            //var clone = new LcArc();
            //clone.Copy(this);
            //return clone;
            var clone = Document.CreateObject<LcArc>();
            clone.Copy(this);
            clone.Initilize(this.Document);
            return clone;
        }

        public override void Copy(LcElement src)
        {
            var arc = ((LcArc)src);
            this.Center = arc.Center;
            this.Radius = arc.Radius;
            this.StartAngle = arc.StartAngle;
            this.EndAngle = arc.EndAngle;
            this.Midp = arc.Midp;
            this.Startp = arc.Startp;
            this.Endp = arc.Endp;
        }

        public void Set(Vector2 center = null, Vector2 start = null, Vector2 mid = null, Vector2 end = null, double? radius = null, double? startAngle = null, double? endAngle = null,bool fireChangedEvent = false)
        {

            //if (!fireChangedEvent)
            //{
            //    if (start != null) this.Startp = start;
            //    if (end != null) this.Endp = end;
            //    if (mid != null) this.Midp = mid;
            //    if (center != null)
            //    {
            //        var oldcenter = Center;
            //        var newcenter = center;
            //        Vector2 movevec = newcenter - oldcenter;
            //        this.Center = center;
            //        this.Startp += movevec;
            //        this.Endp += movevec;
            //        this.Midp += movevec;
            //    }
            //}
            //else
            {
                bool chg_start = (start != null && start != this.Startp);
                bool df = false;
                if (chg_start)
                {
                    OnPropertyChangedBefore(nameof(Startp), this.Startp, start);
                    var oldValue = this.Startp;
                    this.Startp = start;
                    //lcarc.Startp = _position; //开始点
                    //this.Endp = _group.Endp; //结束点
                    //lcarc.Midp = _group.Midp; //圆弧中间点
                    this.Center = GeoUtils.GetCenter(start, this.Midp, this.Endp);
                    
                    Arc2d arc2D = CreateARC(this.Startp, this.Midp, this.Endp,out df);
                    this.Radius = Vector2.Distance(this.Center, this.Startp);
                    if (df)
                    {
                        this.Startp = this.Endp;
                        this.Endp = start;
                    }
                    else
                    {
                        this.Startp = start;
                    }
                    this.StartAngle = arc2D.StartAngle;
                    this.EndAngle = arc2D.EndAngle;
                    this.Midp = Getmidpoint(arc2D, this.Startp);
                    
                    OnPropertyChangedAfter(nameof(Startp), oldValue, this.Startp);
                }
                bool chg_end = (end != null && end != this.Endp);
                if (chg_end)
                {
                    OnPropertyChangedBefore(nameof(Endp), this.Endp, end);
                    var oldValue = this.Endp;
                    this.Endp = end;
                    this.Center =GeoUtils.GetCenter(this.Startp,this.Midp,end);
                    Arc2d arc2D = CreateARC(this.Startp, this.Midp, this.Endp, out df);
                    //Arc2d arc2D = CreatePCE(this.Startp, this.Center, this.Endp,this.Midp);
                    this.Radius = Vector2.Distance(this.Center, this.Startp);
                    if (df)
                    {
                        this.Endp = this.Startp;
                        this.Startp = end;
                    }
                    else
                    {
                        this.Endp = end;
                    }
                    this.StartAngle = arc2D.StartAngle;
                    this.EndAngle = arc2D.EndAngle;
                    this.Midp = Getmidpoint(arc2D, this.Startp);
                    OnPropertyChangedAfter(nameof(Endp), oldValue, this.Endp);
                }
                bool chg_mid = (mid != null && mid != this.Midp);
                if (chg_mid)
                {
                    OnPropertyChangedBefore(nameof(Midp), this.Midp, mid);
                    var oldValue = this.Midp;
                    this.Midp = mid;
                    this.Center = GeoUtils.GetCenter(this.Startp, mid, this.Endp);
                    Arc2d arc2D = CreateARC(this.Startp, this.Midp, this.Endp, out df);
                    this.Radius = Vector2.Distance(this.Center, this.Startp);
                    if (df)
                    {
                        Vector2 point = this.Startp;
                        this.Startp = this.Endp;
                        this.Endp = point;
                    }
                    this.StartAngle = arc2D.StartAngle;
                    this.EndAngle = arc2D.EndAngle;
                    this.Midp = Getmidpoint(arc2D, this.Startp);
                    OnPropertyChangedAfter(nameof(Midp), oldValue, this.Midp);
                }
                bool chg_center = (center != null && center != this.Center);
                if (chg_center)    //如果点击的是圆心
                {
                    var oldcenter = this.Center;
                    var newcenter = center;
                    //移动向量
                    Vector2 movevec = newcenter - oldcenter;
                    OnPropertyChangedBefore(nameof(Center), this.Center, center);
                    var centeroldValue = this.Center;
                    this.Center = center; 
                 
                    OnPropertyChangedAfter(nameof(Center), centeroldValue, this.Center);

                    OnPropertyChangedBefore(nameof(Startp), this.Startp, this.Startp + movevec);
                    var startoldValue = this.Startp;
                    this.Startp = this.Startp + movevec;
                    OnPropertyChangedAfter(nameof(Startp), startoldValue, this.Startp);

                    OnPropertyChangedBefore(nameof(Endp), this.Endp, this.Endp + movevec);
                    var endoldValue = this.Endp;
                    this.Endp = this.Endp + movevec;
                    OnPropertyChangedAfter(nameof(Endp), endoldValue, this.Endp);

                    OnPropertyChangedBefore(nameof(Midp), this.Midp, this.Midp + movevec);
                    var midoldValue = this.Midp;
                    this.Midp = this.Midp + movevec;
                    OnPropertyChangedAfter(nameof(Midp), midoldValue, this.Midp);
                }
                bool chg_radius = (radius != null && radius != this.Radius);
                if (chg_radius)
                {
                    OnPropertyChangedBefore(nameof(Radius), this.Radius, radius);
                    var oldValue = this.Radius;
                    this.Radius = radius.Value;
                    this.Startp.X = this.Center.X + this.Radius * Math.Cos(this.StartAngle);
                    this.Startp.Y = this.Center.Y + this.Radius * Math.Sin(this.StartAngle);
                    this.Endp.X = this.Center.X + this.Radius * Math.Cos(this.EndAngle);
                    this.Endp.Y = this.Center.Y + this.Radius * Math.Sin(this.EndAngle);
                    Arc2d arc2D = CreatePCE(this.Startp, this.Center, this.Endp, this.Midp);
                    this.Midp = Getmidpoint(arc2D, this.Startp);
                    OnPropertyChangedAfter(nameof(Radius), oldValue, this.Radius);
                }
                bool chg_startAngle = (startAngle != null && startAngle != this.StartAngle*180/Math.PI);
                if (chg_startAngle)
                {
                    OnPropertyChangedBefore(nameof(StartAngle), this.StartAngle, startAngle);
                    var oldValue = this.StartAngle;
                    this.StartAngle = startAngle.Value;
                    this.StartAngle=this.StartAngle*Math.PI/180;
                    this.Startp.X = this.Center.X + this.Radius * Math.Cos(this.StartAngle);
                    this.Startp.Y = this.Center.Y + this.Radius * Math.Sin(this.StartAngle);
                    if (this.StartAngle > 360)
                    {
                        this.StartAngle -= 360;
                    }
                    Arc2d arc2D = CreatePCE(this.Startp, this.Center, this.Endp, this.Midp);
                    this.Midp = Getmidpoint(arc2D, this.Startp);
                    OnPropertyChangedAfter(nameof(StartAngle), oldValue, this.StartAngle);
                }
                bool chg_endAngle = (endAngle != null && endAngle != this.EndAngle * 180 / Math.PI);
                if (chg_endAngle)
                {
                    OnPropertyChangedBefore(nameof(EndAngle), this.EndAngle, endAngle);
                    var oldValue = this.EndAngle;
                    this.EndAngle = endAngle.Value;
                    this.EndAngle = this.EndAngle * Math.PI / 180;
                    this.Endp.X = this.Center.X + this.Radius * Math.Cos(this.EndAngle);
                    this.Endp.Y = this.Center.Y + this.Radius * Math.Sin(this.EndAngle);
                    if (this.EndAngle > 360)
                    {
                        this.EndAngle -= 360;
                    }
                    Arc2d arc2D = CreatePCE(this.Startp, this.Center, this.Endp, this.Midp);
                    this.Midp = Getmidpoint(arc2D, this.Startp);
                    OnPropertyChangedAfter(nameof(EndAngle), oldValue, this.EndAngle);
                }
            }
        }
        /// <summary>
        /// 拖拽移动
        /// </summary>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        public override void Translate(double dx, double dy)
        {
            var tc = new Vector2(this.Center.X + dx, this.Center.Y + dy);
            Set(center: tc);
            ResetBoundingBox();
        }
        /// <summary>
        /// 判断角度弧度的转换融合问题
        /// </summary>
        /// <param name="angle"></param>
        /// <param name="angle1"></param>
        /// <param name="m"></param>
        /// <returns></returns>
        public static bool IsAngleTrue(double angle, double angle1, double m = 0.0001)
        {
            if (angle - m < angle1 && angle1 < angle + m)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 创建圆弧
        /// </summary>
        /// <param name="sp"></param>
        /// <param name="cp"></param>
        /// <param name="ep"></param>
        /// <returns></returns>
        public Arc2d CreatePCE(Vector2 sp, Vector2 cp, Vector2 ep, Vector2 mp)
        {
            Arc2d arc2D = new Arc2d();
            arc2D.Center = cp;
            arc2D.StartAngle = (Math.Atan2(sp.Y - cp.Y, sp.X - cp.X) * 180 / Math.PI);
            arc2D.EndAngle = (Math.Atan2(ep.Y - cp.Y, ep.X - cp.X) * 180 / Math.PI);
            arc2D.Radius = Vector2.Distance(cp, sp);
            if (arc2D.StartAngle < 0)
            {
                arc2D.StartAngle += 360;
            }
            if (arc2D.EndAngle < 0)
            {
                arc2D.EndAngle += 360;
            }
            double midAngle = (Math.Atan2(mp.Y - cp.Y, mp.X - cp.X) * 180 / Math.PI);

            if (IsAngleTrue((arc2D.EndAngle - arc2D.StartAngle) + (midAngle - arc2D.StartAngle) + (arc2D.EndAngle - midAngle), 360) == false)
            //if ((arc2D.EndAngle - arc2D.StartAngle) + (midAngle - arc2D.StartAngle) + (arc2D.EndAngle - midAngle) == 360)
            {
                arc2D.StartAngle = arc2D.StartAngle / 180 * Math.PI;
                arc2D.EndAngle = arc2D.EndAngle / 180 * Math.PI;
            }
            else
            {
                Vector2 vector2 = this.Endp;
                this.Endp = this.Startp;
                this.Startp = vector2;
                var sange = arc2D.StartAngle;
                arc2D.StartAngle = arc2D.EndAngle / 180 * Math.PI;
                arc2D.EndAngle = sange / 180 * Math.PI;
            }


            //if (arc2D.StartAngle - arc2D.EndAngle > 0)
            //{

            //    Vector2 vector2 = this.Endp;
            //    this.Endp = this.Startp;
            //    this.Startp = vector2;
            //    var sange = arc2D.StartAngle;
            //    arc2D.StartAngle = arc2D.EndAngle / 180 * Math.PI;
            //    arc2D.EndAngle = sange / 180 * Math.PI;
            //}
            //else
            //{
            //arc2D.StartAngle = arc2D.StartAngle / 180 * Math.PI;
            //    arc2D.EndAngle = arc2D.EndAngle / 180 * Math.PI;
            //}
            return arc2D;
        }

        public static Arc2d CreateARC(Vector2 sp, Vector2 mp, Vector2 ep, out bool df)
        {
            df = false;
            Arc2d arc2D = new Arc2d();
            arc2D.Center = GeoUtils.GetCenter(sp, mp, ep);
            //this.center = arc2D.Center;
            arc2D.Radius = Vector2.Distance(sp, arc2D.Center);
            double Degrees, smidAngle, emidAngle;
            arc2D.StartAngle = GetDegreesByTwoLine(new(arc2D.Center.X, arc2D.Center.Y), new(arc2D.Center.X + arc2D.Radius, arc2D.Center.Y), new(arc2D.Center.X, arc2D.Center.Y), new(sp.X, sp.Y)); //计算圆弧的起始角度
            arc2D.EndAngle = GetDegreesByTwoLine(new(arc2D.Center.X, arc2D.Center.Y), new(arc2D.Center.X + arc2D.Radius, arc2D.Center.Y), new(arc2D.Center.X, arc2D.Center.Y), new(ep.X, ep.Y));  //计算圆弧的结束角度
            //smidAngle = GetDegreesByTwoLine(new(arc2D.Center.X, arc2D.Center.Y), new(sp.X, sp.Y), new(arc2D.Center.X, arc2D.Center.Y), new(mp.X, mp.Y));  //起始点到中点之间的角度
            //emidAngle = GetDegreesByTwoLine(new(arc2D.Center.X, arc2D.Center.Y), new(ep.X, ep.Y), new(arc2D.Center.X, arc2D.Center.Y), new(mp.X, mp.Y));
            if (IsTopInLine(arc2D.Center, sp, new(arc2D.Center.X + arc2D.Radius, arc2D.Center.Y)) < 0)
            {
                arc2D.StartAngle = 360 - arc2D.StartAngle;
            }
            if (IsTopInLine(arc2D.Center, ep, new(arc2D.Center.X + arc2D.Radius, arc2D.Center.Y)) < 0)
            {
                arc2D.EndAngle = 360 - arc2D.EndAngle;
            }
            var ms = IsTopInLine(arc2D.Center, sp, mp);
            var me = IsTopInLine(arc2D.Center, ep, mp);
            var sm = IsTopInLine(arc2D.Center, ep, sp);
            bool zh = false;
            if ((ms == me && sm < 0) || (me > 0 && ms < 0))
            {
                zh = true;
            }

            //double moveAngle = smidAngle + emidAngle;
            //double xAngle = arc2D.EndAngle - arc2D.StartAngle;
            //if (xAngle < 0)
            //{
            //    xAngle += 360;
            //}
            //if (LcArc.IsAngleTrue(xAngle, moveAngle) == true)
            if (zh)
            {
                arc2D.StartAngle = arc2D.StartAngle / 180 * Math.PI;
                arc2D.EndAngle = arc2D.EndAngle / 180 * Math.PI;
            }
            else
            {
                Degrees = arc2D.StartAngle;
                df = true;
                //this.startPoint = ep;
                //this.endPoint = sp;
                arc2D.StartAngle = arc2D.EndAngle / 180 * Math.PI;
                arc2D.EndAngle = Degrees / 180 * Math.PI;
            }
            return arc2D;
        }

        public static double GetDegreesByTwoLine(Vector2 line1start, Vector2 line1End, Vector2 line2start, Vector2 line2End)
        {
            double x1 = line1start.X;
            double y1 = line1start.Y;
            double x2 = line1End.X;
            double y2 = line1End.Y;
            double x3 = line2start.X;
            double y3 = line2start.Y;
            double x4 = line2End.X;
            double y4 = line2End.Y;
            // 计算线段的向量表示
            double v1x = x2 - x1;
            double v1y = y2 - y1;
            double v2x = x4 - x3;
            double v2y = y4 - y3;
            // 计算向量的内积
            double dotProduct = v1x * v2x + v1y * v2y;
            // 计算向量的长度
            double magnitudeV1 = Math.Sqrt(v1x * v1x + v1y * v1y);
            double magnitudeV2 = Math.Sqrt(v2x * v2x + v2y * v2y);
            // 计算夹角余弦值
            double cosine = dotProduct / (magnitudeV1 * magnitudeV2);
            // 将夹角余弦值转换为角度
            double angleRadians = Math.Acos(cosine);
            double angleDegrees = angleRadians * 180 / Math.PI;
            return angleDegrees;
        }

        public static int IsTopInLine(Vector2 line1start, Vector2 line1End, Vector2 point)
        {
            Vector2 S;
            Vector2 E;
            S = line1End;
            E = line1start;
            double Tmp = (S.Y - E.Y) * point.X + (E.X - S.X) * point.Y + S.X * E.Y - E.X * S.Y;
            if (Tmp == 0)
            {
                return 0;
            }
            if (Tmp > 0)
            {
                return 1;
            }
            else
            { return -1; }
        }

        public override List<Vector2> GetCrossVectorByLine(Line2d element)
        {
            List<Vector2> points = GeoUtils.GetCrossLineArc(element.Start, element.End, this.Center, this.Radius);
            return points;
            //List<Vector2> points2=new List<Vector2>();
            //if (points.Count !=0)
            //{
            //    foreach(Vector2 point in points)
            //    {
            //        if (GeoUtils.IsPointOnLineExtension(element.Start, element.End, point))
            //        {
            //        }
            //        else
            //        {
            //            points2.Add(point);
            //        }
            //    }
            //}
            //return points2;
        }
        public override List<Vector2> GetCrossVectorByArc(Arc2d arc2D)  //相当于是圆与圆之间交点的计算
        {
            //List<Vector2> points = new List<Vector2>();
            List<Vector2> points =GeoUtils.ArcCrossArc(this.Arc, arc2D);
            return points;
            //List<Vector2> endpoints = new List<Vector2>();
            //if(points != null)
            //{
            //    foreach (var item in points)
            //    {
            //         //&& GeoUtils.IsPointOnArcExtension(arc2D, item)
            //        if (!Arc2d.PointInArc(item, arc2D.Startp, arc2D.Endp, arc2D.Center))
            //        {
            //            endpoints.Add(item);
            //        }
            //    }
            //}
            
            //return endpoints;
        }
        public override List<Vector2> GetCrossVectorByCircle(Circle2d ele)
        {
            //List<Vector2> points = new List<Vector2>();
            List<Vector2> points = GeoUtils.CircleCrossArc(ele,this.Arc);
            //List<Vector2> endpoints = new List<Vector2>();
            //if (points != null)
            //{
            //    foreach (var item in points)
            //    {
            //        if (  !GeoUtils.IsPointOnArcExtension(this.Arc, item))
            //        {
            //            endpoints.Add(item);
            //        }
            //    }
            //}

            return points;

        }

        public Vector2 Getmidpoint(Arc2d arc2D,Vector2 sp)
        {

            var sage = arc2D.StartAngle * 180 / Math.PI;
            var eage = arc2D.EndAngle * 180 / Math.PI;
            double moveAngle = eage - sage;
            if (moveAngle < 0)
            {
                moveAngle += 360;
            }
            double midAngle = (moveAngle / 2);  //需要旋转的角度
            var matrix3 = Matrix3.Rotate(midAngle, arc2D.Center); //围绕圆心旋转
            var mp = matrix3.MultiplyPoint(sp); //旋转矩阵是逆时针旋转
            return new Vector2(mp.X, mp.Y);
        }

        public override void WriteProperties(Utf8JsonWriter writer, JsonSerializerOptions soptions)
        {
            base.WriteProperties(writer, soptions);
            writer.WriteVector2dProperty(nameof(this.Center), this.Center);
            writer.WriteNumberProperty(nameof(this.Radius), this.Radius);
            writer.WriteNumberProperty(nameof(this.StartAngle), this.StartAngle);
            writer.WriteNumberProperty(nameof(this.EndAngle), this.EndAngle);
            writer.WriteNumberProperty(nameof(this.MoveAngle), this.MoveAngle);
            writer.WriteVector2dProperty(nameof(this.Startp), this.Startp);
            writer.WriteVector2dProperty(nameof(this.Endp), this.Endp);
            writer.WriteVector2dProperty(nameof(this.Midp), this.Midp);
            writer.WriteNumberProperty(nameof(this.ArcLength), this.ArcLength);
        }


        public override void ReadProperties(ref JsonElement jele)
        {
            base.ReadProperties(ref jele);
            this.Center = jele.ReadVector2dProperty(nameof(this.Center));
            this.Radius = jele.ReadDoubleProperty(nameof(this.Radius));
            this.StartAngle = jele.ReadDoubleProperty(nameof(this.StartAngle));
            this.EndAngle = jele.ReadDoubleProperty(nameof(this.EndAngle));
            this.MoveAngle = jele.ReadDoubleProperty(nameof(this.MoveAngle));
            this.Startp = jele.ReadVector2dProperty(nameof(this.Startp));
            this.Endp = jele.ReadVector2dProperty(nameof(this.Endp));
            this.Midp = jele.ReadVector2dProperty(nameof(this.Midp));
            this.ArcLength = jele.ReadDoubleProperty(nameof(this.ArcLength));
        }
        public override bool PointInElement(Vector2 point, double epsilon = 0.001)
        {
            if(Math.Abs(Math.Sqrt(Math.Pow(this.Center.X - point.X, 2) + Math.Pow(this.Center.Y - point.Y, 2)) - this.Radius) <= epsilon)
            {
                Vector2 center = this.Center;
                Vector2 sp = this.Startp;
                Vector2 ep = this.Endp;
                var ms = IsTopInLine(center, sp, point);
                var me = IsTopInLine(center, ep, point);
                var sm = IsTopInLine(center, ep, sp);
                if ((ms == me && sm < 0) || (me > 0 && ms < 0))
                 {
                    return true;
                 }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

    }
}
